﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Windows.Threading;
using System.ComponentModel;
using System.Deployment.Application;
using System.Reflection;
using System.Windows;
using System.Xml;
using System.IO;
using System.Deployment.Internal;


namespace Utilities
{
    public class ClickOnceExt : INotifyPropertyChanged
    {
        #region Events
        public event EventHandler Restarting;
        private void OnRestarting()
        {
            var handler = Restarting;
            if (handler == null) return;
            handler(this, EventArgs.Empty);
        }
        #endregion

        //private Timer tmrCheckUpdate = new Timer((TimerCallback)((_1) => { }));
        private DispatcherTimer tmrCheckUpdate = new DispatcherTimer();

        private ApplicationDeployment ad;

        public ClickOnceExt()
        {
            if (!ApplicationDeployment.IsNetworkDeployed) return;
            Init();
            SoftwareVersion = ad.CurrentVersion.ToString();
            tmrCheckUpdate.Tick += new EventHandler(tmrCheckUpdate_Tick);
        }

        #region IsClickOnce
        public bool IsClickOnce
        {
            get { return ApplicationDeployment.IsNetworkDeployed; }
        }
        #endregion

        #region SoftwareVersion
        private string softwareVersion = Environment.Version.ToString();
        public string SoftwareVersion
        {
            get { return softwareVersion; }
            private set
            {
                softwareVersion = value;
                OnPropertyChanged("SoftwareVersion");
            }
        }
        #endregion

        #region IsCheckingUpdate
        private bool isCheckingUpdate;
        public bool IsCheckingUpdate
        {
            get { return isCheckingUpdate; }
            private set
            {
                if (isCheckingUpdate == value) return;
                isCheckingUpdate = value;
                OnPropertyChanged("IsCheckingUpdate");
            }
        }
        #endregion

        #region IsAutoUpdate
        private bool isAutoUpdate;
        public bool IsAutoUpdate
        {
            get { return isAutoUpdate; }
            set 
            {
                isAutoUpdate = value;
                tmrCheckUpdate.IsEnabled = value;
                OnPropertyChanged("IsAutoUpdate");
            }
        }
        #endregion

        #region CheckUpdateInterval
        private TimeSpan checkUpdateInterval;
        public TimeSpan CheckUpdateInterval
        {
            get { return tmrCheckUpdate.Interval; }
            set { tmrCheckUpdate.Interval = value;}
        }
        #endregion

        #region IsRestartWhenUpdate
        private bool isRestartWhenUpdate;
        public bool IsRestartWhenUpdate
        {
            get { return isRestartWhenUpdate; }
            set
            {
                if (isRestartWhenUpdate == value) return;
                isRestartWhenUpdate = value;
                OnPropertyChanged("IsRestartWhenUpdate");
                if (isRestartWhenUpdate && IsUpdateComplete) Restart();
            }
        }
        #endregion

        #region IsUpdateComplete
        private bool isUpdateComplete;
        public bool IsUpdateComplete
        {
            get { return isUpdateComplete; }
            set
            {
                if (isUpdateComplete == value) return;
                isUpdateComplete = value;
                OnPropertyChanged("IsUpdateComplete");
            }
        }
        #endregion

        #region IsFirstRun
        public bool IsFirstRun
        {
            get 
            {
                if (ad != null) return ad.IsFirstRun;
                return false; 
            }
        }
        #endregion
        
        


        
        

        private void Init()
        {
            ad = ApplicationDeployment.CurrentDeployment;
            ad.CheckForUpdateCompleted += new CheckForUpdateCompletedEventHandler(ad_CheckForUpdateCompleted);
            ad.UpdateCompleted += new AsyncCompletedEventHandler(ad_UpdateCompleted);
        }

        void ad_UpdateCompleted(object sender, AsyncCompletedEventArgs e)
        {
            OnPropertyChanged("SoftwareVersion");
            IsUpdateComplete = true;
            if(IsRestartWhenUpdate) Restart();
        }

        public void CheckUpdate()
        {
            if (!IsClickOnce || IsCheckingUpdate || IsUpdateComplete) return;
            IsCheckingUpdate = true;
            ad.CheckForUpdateAsync();
        }

        private void Restart()
        {
            OnRestarting();
            //Перезапускаем приложение
            System.Windows.Forms.Application.Restart();
            Environment.Exit(1);
            //System.Windows.Application.Current.Shutdown();
        }

        void ad_CheckForUpdateCompleted(object sender, CheckForUpdateCompletedEventArgs e)
        {
            if (e.Error != null)
            {
                Init();
                return;
            }
            IsCheckingUpdate = false;

            if (e.UpdateAvailable)
            {
                ad.UpdateAsync();
            }
            else
            {
                tmrCheckUpdate.IsEnabled = IsAutoUpdate;
            }
        }

        void tmrCheckUpdate_Tick(object sender, EventArgs e)
        {
            tmrCheckUpdate.Stop();
            CheckUpdate();
        }

        #region INotifyPropertyChanged Members

        public event PropertyChangedEventHandler PropertyChanged;
        private void OnPropertyChanged(string propertyName)
        {
            var handle = PropertyChanged;
            if (handle == null) return;
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }

        #endregion
    }
}




